home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume24 / lb < prev    next >
Encoding:
Internet Message Format  |  1991-06-05  |  32.5 KB

  1. Subject:  v24i088:  Simple load-balancing program
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 857df0d3 76ae7246 72b0351d a8f66778
  5.  
  6. Submitted-by: Dikran Kassabian <deke@ee.rochester.edu>
  7. Posting-number: Volume 24, Issue 88
  8. Archive-name: lb
  9.  
  10.  
  11. LB is a load-balancing program.  It can check the current load on various
  12. machines on a LAN, and find the best candidate machine to accept a new job
  13. to it's run queue.  Additionally, it can send the job to that machine
  14. using rsh(1).
  15.  
  16. LB works best in homogeneous environments, where each machine has similar
  17. or identical file system layout.  Here at the University of Rochester
  18. Department of Electrical Engineering, we have nearly 70 SUN computers,
  19. which share home-directories and local binaries.  When a user sitting at a
  20. small workstation wants to run a compute intensive job, LB helps to find a
  21. machine on the network that has a low load, knowing that that machine will
  22. also have his/her home directory and required program.
  23.  
  24. #! /bin/sh
  25. # This is a shell archive.  Remove anything before this line, then feed it
  26. # into a shell via "sh file" or similar.  To overwrite existing files,
  27. # type "sh file -c".
  28. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  29. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  30. # Contents:  INSTALL Makefile OTHER_SERVERS README config.h lb.1 lb.5
  31. #   rsdclnt.c srvclnt.c st_sendrecv.c stats.h
  32. # Wrapped by rsalz@litchi.bbn.com on Thu Jun  6 12:43:40 1991
  33. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  34. echo If this archive is complete, you will see the following message:
  35. echo '          "shar: End of archive."'
  36. if test -f 'INSTALL' -a "${1}" != "-c" ; then 
  37.   echo shar: Will not clobber existing file \"'INSTALL'\"
  38. else
  39.   echo shar: Extracting \"'INSTALL'\" \(1988 characters\)
  40.   sed "s/^X//" >'INSTALL' <<'END_OF_FILE'
  41. X
  42. X        LB - The Load Balancer (version 1.2)
  43. X            by Dikran Kassabian
  44. X
  45. X              University Of Rochester
  46. X        Department of Electrical Engineering
  47. X            March 3, 1991
  48. X
  49. XINSTALLATION NOTES:
  50. X
  51. X
  52. X1. CHOOSING A SERVER
  53. X====================
  54. XThe lb load balancer uses statistics gathered via connection with
  55. Xservers on each of the candidate machines.  Two servers are supported,
  56. Xthe SUN rstatd, and Dave Curry's statsrv.  The installer must see to
  57. Xit that all candidate machines support the selected server program.
  58. XIn an all SUN environment, rstatd is the better choice as it seems to
  59. Xbe somewhat faster.  In other environments, it may be necessary to use
  60. Xthe statsrv server, which is public domain.
  61. X
  62. X2. BUILDING THE PROGRAM
  63. X=======================
  64. XOnce a server is selected, the Makefile must be edited to reflect the 
  65. Xchoice.  If rstatd is to be used, edit the Makefile definition for SERVER
  66. Xto be 'SERVER=rstatd'.  If the statsrv server is to be used, make it
  67. X'SERVER=statsrv'.  Check the defines in config.h, and choose the location
  68. Xof the configuration file.  Remember that every machine that wants to
  69. Xuse lb needs to be able to see that configuration file.  You may choose
  70. Xto use multiple copies, or a single copy that all machines can see.  Once
  71. Xthe Makefile and config.h are setup to your satisfaction, type 'make'.
  72. XThe program 'lb' will be built.
  73. X
  74. X3. WRITING THE CONFIGURATION FILE
  75. X=================================
  76. XThe configuration file contains information on every machine on which lb
  77. Xmay start jobs. See the man page lb(5) for details on its setup.
  78. X
  79. X
  80. X4. INSTALLING THE FILES
  81. X=======================
  82. XInstall the program lb in a location within the path of the users requiring
  83. Xit.  Good choices would include /usr/local/bin or /usr/new.  Then install
  84. Xthe configuration file wherever the config.h file claimed it would be.  Again,
  85. Xremember that every machine needs to have read access to this file.  Finally,
  86. Xinstall the man pages lb(1) and lb(5) as appropriate.
  87. X
  88. XThat's all!
  89. X
  90. X
  91. XDeke Kassabian, 3/8/91
  92. END_OF_FILE
  93.   if test 1988 -ne `wc -c <'INSTALL'`; then
  94.     echo shar: \"'INSTALL'\" unpacked with wrong size!
  95.   fi
  96.   # end of 'INSTALL'
  97. fi
  98. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  99.   echo shar: Will not clobber existing file \"'Makefile'\"
  100. else
  101.   echo shar: Extracting \"'Makefile'\" \(1069 characters\)
  102.   sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  103. X#
  104. X# Makefile for "lb", the load-balancer
  105. X# ^Deke Kassabian 6/3/88,  mods and additions 3/7/89
  106. X#
  107. XSERVER=rstatd
  108. X#
  109. X#CFLAGS=  -g -f68881
  110. XCFLAGS=   -O 
  111. XLDFLAGS=  -s
  112. X#PRINT=    ptroff -man
  113. XPRINT=      troff -t -man 
  114. X
  115. XSRCS=      rsdclnt.c srvclnt.c st_sendrecv.c stats.h config.h
  116. XMANS=      lb.1 lb.5
  117. XOBJS_SRV= srvclnt.o st_sendrecv.o
  118. XOBJS_RSD= rsdclnt.o 
  119. XLIBS=     -lrpcsvc
  120. X
  121. Xlb: lb.$(SERVER)
  122. X    @echo "lb has been built for $(SERVER) server."
  123. X
  124. Xlb.rstatd: $(OBJS_RSD)
  125. X    $(CC) $(CFLAGS) $(LDFLAGS) -o lb $(OBJS_RSD) $(LIBS)
  126. X
  127. Xlb.statsrv: $(OBJS_SRV)
  128. X    $(CC) $(CFLAGS) $(LDFLAGS) -o lb $(OBJS_SRV)
  129. X
  130. Xtags:
  131. X    ctags *.c > tags
  132. X
  133. Xclean:
  134. X    rm -f core *.o
  135. X
  136. Xspotless:
  137. X    rm -f core lb *.o
  138. X
  139. Xlove:
  140. X    @echo 'not war?'
  141. X
  142. Xjoke: 
  143. X    @echo 'What do you want for nothing?'
  144. X
  145. Xshar: 
  146. X    @shar Makefile README INSTALL OTHER_SERVERS $(MANS) $(SRCS) >lb.shar
  147. X    @chmod a+r lb.shar
  148. X    @echo "SHAR file lb.shar created."
  149. X
  150. Xhardcopy:
  151. X    lpr README INSTALL OTHER_SERVERS $(SRCS)
  152. X    $(PRINT) $(MANS) | lpr -t
  153. X
  154. X# Dependencies
  155. Xlbmain.o:     lbmain.c stats.h config.h
  156. Xst_sendrecv.o:    st_sendrecv.c stats.h config.h
  157. Xrsdclnt.o:    rsdclnt.c config.h
  158. END_OF_FILE
  159.   if test 1069 -ne `wc -c <'Makefile'`; then
  160.     echo shar: \"'Makefile'\" unpacked with wrong size!
  161.   fi
  162.   # end of 'Makefile'
  163. fi
  164. if test -f 'OTHER_SERVERS' -a "${1}" != "-c" ; then 
  165.   echo shar: Will not clobber existing file \"'OTHER_SERVERS'\"
  166. else
  167.   echo shar: Extracting \"'OTHER_SERVERS'\" \(1224 characters\)
  168.   sed "s/^X//" >'OTHER_SERVERS' <<'END_OF_FILE'
  169. X
  170. XWHAT?  No rstatd?  No statsrv?  Fear not.
  171. X------------------------------------------
  172. X
  173. XLB is simple enough to modify for use with other servers.  This package
  174. Xincludes client programs to talk to rstatd or statsrv, and these clients
  175. Xcan be used as templates for others.
  176. X
  177. Xstatsrv is available from comp.sources.unix archive servers.
  178. X
  179. X-------------------------------------------------------------------------
  180. XFrom the SunOS rstatd manual page:
  181. X
  182. X  rstatd is a  server  which  returns  performance  statistics obtained  
  183. X  from the kernel.  The rstatd daemon is normally invoked by inetd(8C).
  184. X
  185. X-------------------------------------------------------------------------
  186. XThe opening paragraph from Dave Curry's statsrv README file:
  187. X
  188. X  This is a remote statistics server as described in RFC996, "Statistics
  189. X  Server", D. L. Mills, February 1987.  With it, you can collect things
  190. X  like load averages, number of users, uptime, and network statistics
  191. X  from remote machines easily.  (David Curry, davy@riacs.edu)
  192. X-------------------------------------------------------------------------
  193. X
  194. X      ^Deke Kassabian,   deke@ee.rochester.edu   or   ur-valhalla!deke
  195. X   Univ of Rochester, Dept of EE, Rochester, NY 14627     (+1 716-275-3106)
  196. END_OF_FILE
  197.   if test 1224 -ne `wc -c <'OTHER_SERVERS'`; then
  198.     echo shar: \"'OTHER_SERVERS'\" unpacked with wrong size!
  199.   fi
  200.   # end of 'OTHER_SERVERS'
  201. fi
  202. if test -f 'README' -a "${1}" != "-c" ; then 
  203.   echo shar: Will not clobber existing file \"'README'\"
  204. else
  205.   echo shar: Extracting \"'README'\" \(2930 characters\)
  206.   sed "s/^X//" >'README' <<'END_OF_FILE'
  207. X        LB - The Load Balancer (version 1.2)
  208. X            by Dikran Kassabian
  209. X
  210. X              University Of Rochester
  211. X        Department of Electrical Engineering
  212. X            March 3, 1991
  213. X_______________________________________________________________________
  214. X
  215. XWhat is LB?
  216. X
  217. X    LB is a load-balancing program.  It can check the current
  218. X    load on various machines on a LAN, and find the best candidate
  219. X    machine to accept a new job to it's run queue.  Additionally,
  220. X    it can send the job to that machine using rsh(1).
  221. X
  222. X    LB works best in homogeneous environments, where each machine
  223. X    has similar or identical file system layout.  Here at the
  224. X    University of Rochester Department of Electrical Engineering,
  225. X    we have nearly 70 SUN computers, which share home-directories
  226. X    and local binaries.  When a user sitting at a small workstation
  227. X    wants to run a compute intensive job, LB helps to find a machine
  228. X    on the network that has a low load, knowing that that machine
  229. X    will also have his/her home directory and required program.
  230. X
  231. XHow to install LB:
  232. X
  233. X    A separate file, called INSTALL, is included with detailed
  234. X    installation notes, but briefly...
  235. X
  236. X    To install lb, unpack the shar file (hmm, I guess you've already
  237. X    done that :-), decide which statistics server you want to use
  238. X    (rstatd or statsrv) and make the two small adjustments to the
  239. X    Makefile, then type "make".  The program 'lb' will be produced.
  240. X    Then move 'lb' to an appropriate directory (/usr/local/bin),
  241. X    edit and install the configuration file, and you're ready to 
  242. X    go.  The relevant man pages are included, and can be installed 
  243. X    in your local man page directory.
  244. X
  245. XHow to use LB:
  246. X
  247. X    To use lb, just type 'lb <command-line>' at your prompt, where
  248. X    <command line> is some shell command you might normally type
  249. X    at your prompt.  LB will read a configuration file that tells
  250. X    it about the candidate machines, select one, and then use rsh(1)
  251. X    to run <command-line> on the specified machine.
  252. X
  253. X    See the man page for lb(1) for more information.
  254. X
  255. XSpecial thanks to Dave Curry (davy@riacs.edu), whose statsrv server can
  256. Xbe used as an option to the rpc.rstatd server.  He was nice enough to let
  257. Xme include some of his code with this package.  The files st_sendrecv.c
  258. Xand stats.h are directly from his statsrv distribution.
  259. X
  260. XThis version of lb has been tested in only a few environments.  It works on 
  261. Xour Sun-3 and Sun-4 computers under SunOS 4.1.  It also works on our 68030
  262. XNeXT Cubes under 1.0a OS.  Previous versions ran on our Vax 11/750 under 
  263. XMt.Xinu BSD (but that machine has since been retired).  Beyond that I don't 
  264. Xknow.  If you port it to other operating systems and hardware, send me the 
  265. Xdiffs so I can include them in the next release (if there is one).
  266. X
  267. XIf you have comments/fixes/bug-reports/flames, send 'em to me at
  268. Xdeke@ee.rochester.edu.  I'll make every effort to reply, and to address
  269. Xyour concerns, but can't always guarantee that I can be quick about it.
  270. X
  271. XGood luck with lb!  I hope you find it useful.
  272. END_OF_FILE
  273.   if test 2930 -ne `wc -c <'README'`; then
  274.     echo shar: \"'README'\" unpacked with wrong size!
  275.   fi
  276.   # end of 'README'
  277. fi
  278. if test -f 'config.h' -a "${1}" != "-c" ; then 
  279.   echo shar: Will not clobber existing file \"'config.h'\"
  280. else
  281.   echo shar: Extracting \"'config.h'\" \(730 characters\)
  282.   sed "s/^X//" >'config.h' <<'END_OF_FILE'
  283. X/*                            */
  284. X/* Configuration parameters for the load balancer, 'lb' */
  285. X/* Copyright (c) 1988, 1989 University of Rochester     */
  286. X/* Department of Electrical Engineering.                */
  287. X/*                            */
  288. X
  289. X#define    CONFIGFILE    "/usr/share/lb.conf"
  290. X#define    RSH        "/usr/ucb/rsh"
  291. X
  292. X#define loadavg(sp,n)  (((float) (sp)->avenrun[n]) / 256.0)
  293. X#define MAXLINE        255        /* largest line in config file*/
  294. X#define MAXSHBUF    10240        /* max size of shell buffer   */
  295. X#define MAXHOST        64        /* longest allowable hostname */
  296. X
  297. X#if u3b || u3b5 || sun
  298. X#define MAXFLOAT    ((float)3.40282346638528860e+38)
  299. X#endif
  300. X
  301. X#if pdp11 || vax
  302. X#define MAXFLOAT    ((float)1.701411733192644299e+38)
  303. X#endif
  304. X
  305. X#ifndef MAXFLOAT
  306. X#define MAXFLOAT    ((float)1.701411733192644299e+38)
  307. X#endif
  308. END_OF_FILE
  309.   if test 730 -ne `wc -c <'config.h'`; then
  310.     echo shar: \"'config.h'\" unpacked with wrong size!
  311.   fi
  312.   # end of 'config.h'
  313. fi
  314. if test -f 'lb.1' -a "${1}" != "-c" ; then 
  315.   echo shar: Will not clobber existing file \"'lb.1'\"
  316. else
  317.   echo shar: Extracting \"'lb.1'\" \(2521 characters\)
  318.   sed "s/^X//" >'lb.1' <<'END_OF_FILE'
  319. X.tr ~ \ 
  320. X.TH LB 1 "options
  321. X.SH NAME
  322. XLb \-  load balancer for homogeneous environment
  323. X.SH SYNOPSIS
  324. X.BR "lb [ -v | -q ] <command string>
  325. X.PP
  326. X.SH DESCRIPTION
  327. X.I lb
  328. Xfinds the best machine in the environment on which to run a batch type
  329. Xcompute task.  This is done by comparing load averages
  330. Xand computing power for various machines, and selecting the machine
  331. Xbest able to accept the compute task.
  332. X.I lb
  333. Xis especially useful in distributing compute intensive jobs among
  334. Xthe many computers in a homogeneous environment.
  335. X.sp
  336. X.SH OPTIONS
  337. XWith no options,
  338. X.I lb
  339. Xprints a one line output identifying
  340. Xthe selected machine and the command being submitted.
  341. X.sp
  342. X.nf
  343. X    -v    verbose mode:  causes an excessive amount of
  344. X        information about the determination of the best
  345. X        machine selection to be printed.
  346. X
  347. X    -q    quiet mode:  causes even the usual one line
  348. X        output identifying the selected machine to be
  349. X        eliminated.  The job will be sent to the remote
  350. X        machine, but you will never be told which machine
  351. X        was selected!
  352. X.fi
  353. X.SH EXAMPLES
  354. X.nf
  355. X.I lb
  356. X.fi
  357. X    This gives the output of lb -v, but executes no command
  358. X.sp
  359. X.nf
  360. X.I lb fortune
  361. X.fi
  362. X    This executes "fortune" on the least loaded machine.
  363. X.sp
  364. X.nf
  365. X.I lb -v foobar
  366. X.fi
  367. X    This executes "foobar" on the least loaded machine, and gives
  368. Xverbose messages.
  369. X.sp
  370. X.nf
  371. X.I lb -q minimos infile
  372. X.fi
  373. X    This executes "minimos infile" on the least loaded machine,
  374. Xand gives no messages.
  375. X.sp
  376. X.nf
  377. X.I lb 'spice<infile>outfile'
  378. X.fi
  379. X    This is an important example.  Here, a program called "spice" is
  380. Xbeing run with redirected input and output. Anytime redirection is 
  381. Xdesired in using
  382. X.I lb,
  383. Xthe portion using redirection must be quoted to avoid interpretation at
  384. Xthe originating shell.  The quoted string in this example allows for the
  385. Xredirection to take place on the remote machine.
  386. X.sp
  387. X.nf
  388. X.SH FILES
  389. X.fi
  390. X.I lb
  391. Xalso requires the configuration file
  392. X.I lb.conf
  393. Xwhich lists machines to be
  394. Xconsidered, and some basic information about them.  See the manual
  395. Xpage lb(5) for more on the configuration file.
  396. X.nf
  397. X.SH CAVEATS
  398. X.fi
  399. X.sp
  400. X.I lb
  401. Xshould really use
  402. X.I csh job control
  403. Xso that the user may track the progress of the submitted job.  Maybe in
  404. Xthe next version.
  405. X.sp
  406. X.nf
  407. X.SH NOTES
  408. XThis program is still under development.  Send 
  409. Xdescriptions of problems and/or comments to deke@ee.rochester.edu
  410. X(also ...!rochester!ur-valhalla!deke).
  411. X.SH AUTHOR
  412. X.nf
  413. XDikran Kassabian,
  414. XUniversity of Rochester Dept. of Electrical Engineering
  415. XRochester, NY 14627 (716) 275-3106
  416. X.SH "SEE ALSO"
  417. Xrstatd(8), statsrv(8), w(1), uptime(1), lb(5)
  418. END_OF_FILE
  419.   if test 2521 -ne `wc -c <'lb.1'`; then
  420.     echo shar: \"'lb.1'\" unpacked with wrong size!
  421.   fi
  422.   # end of 'lb.1'
  423. fi
  424. if test -f 'lb.5' -a "${1}" != "-c" ; then 
  425.   echo shar: Will not clobber existing file \"'lb.5'\"
  426. else
  427.   echo shar: Extracting \"'lb.5'\" \(2063 characters\)
  428.   sed "s/^X//" >'lb.5' <<'END_OF_FILE'
  429. X.tr ~ \ 
  430. X.TH LB 5 "limit
  431. X.SH NAME
  432. XLb.conf \-  load balancer configuration file for lb(1)
  433. X.fi
  434. X.SH DESCRIPTION
  435. XThis file contains information about local machines recognized by
  436. X.IR lb (1).
  437. XThe format consists of single line entries with three fields. The
  438. Xfields are
  439. X.I machine-name,
  440. X.I power-factor,
  441. Xand
  442. X.I load-limit.
  443. X.sp
  444. X.I machine-name
  445. Xis a legal or recognized hostname which is to be a candidate for jobs
  446. Xinitiated through the use of lb(1).  This machine must support the
  447. Xstatistics server protocol used by lb(1).
  448. X.sp
  449. X.I power-factor
  450. Xis a floating point value, and has meaning only by comparison to
  451. Xthe power-factors of other machines.  The machines with the larger
  452. Xpower-factors will be preferred to those with smaller power-factors.
  453. X.sp
  454. X.I load-limit
  455. Xspecifies the load-average beyond which jobs should not be sent
  456. Xto that machine.
  457. X.sp
  458. X.SH SAMPLE FILE
  459. X.nf
  460. X# lb.conf
  461. X#
  462. X# The format of this file is <machine> <sfactor> <limit>
  463. X.ta .8i
  464. X# where    <machine> is a legal machine name
  465. X#    <sfactor> is that machines selection factor
  466. X#    <limit>   is the load limit for that machine
  467. X#
  468. X.ta 2.2i 3.2i
  469. X#  MACHINE    SFACTOR    LIMIT
  470. Xbrahms.fubar.com    200    3.0
  471. Xmozart.fubar.com    150    2.5
  472. Xchopin.fubar.com    120    2.5
  473. Xbach.fubar.com    100    1.5
  474. X.sp
  475. X.fi
  476. XLines beginning with 
  477. X.B # 
  478. Xare comments.
  479. X.sp
  480. XIn this example, brahms.fubar.com is preferred to mozart.fubar.com, which
  481. Xis preferred to chopin.fubar.com, if their loads are exactly equal.  In
  482. Xpractice, the load average (number of jobs in the run queue over the last
  483. Xminute) is compared to the load-limit and then divided by the power-factor,
  484. Xfor each machine listed.  If the load average exceeds the load-limit, that
  485. Xmachine will not be considered.  When all machines listed have been considered,
  486. Xthe one with the smallest value of (load-average/power-factor) will be
  487. Xselected.
  488. X.sp
  489. X.SH "SEE ALSO"
  490. Xlb(1), w(1), uptime(1)
  491. X.SH NOTES
  492. XThere are limits to the line-length and the hostname length, which are
  493. Xset in the file config.h when lb(1) is built.  By default, these are
  494. X255 and 64 respectively, but may be tweaked at the installers discretion.
  495. END_OF_FILE
  496.   if test 2063 -ne `wc -c <'lb.5'`; then
  497.     echo shar: \"'lb.5'\" unpacked with wrong size!
  498.   fi
  499.   # end of 'lb.5'
  500. fi
  501. if test -f 'rsdclnt.c' -a "${1}" != "-c" ; then 
  502.   echo shar: Will not clobber existing file \"'rsdclnt.c'\"
  503. else
  504.   echo shar: Extracting \"'rsdclnt.c'\" \(5598 characters\)
  505.   sed "s/^X//" >'rsdclnt.c' <<'END_OF_FILE'
  506. X/*
  507. X * Copyright (c) 1989,1990,1991 University of Rochester
  508. X * Department of Electrical Engineering
  509. X * All rights reserved.
  510. X *
  511. X * Redistribution and use in source and binary forms are permitted
  512. X * provided that the above copyright notice and this paragraph are
  513. X * duplicated in all such forms and that any documentation,
  514. X * advertising materials, and other materials related to such
  515. X * distribution and use acknowledge that the software was developed
  516. X * at the University of Rochester.
  517. X *
  518. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  519. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  520. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  521. X */
  522. X
  523. X/*
  524. X * rsdclnt.c  for the 'lb' load balancer 
  525. X *   -Deke Kassabian, University of Rochester EE Department
  526. X *   ( deke@ee.rochester.edu )  (716) 275-3106
  527. X *
  528. X * $Revision: 1.2 $
  529. X * $Author: deke $
  530. X * $Date: 91/03/03 17:52:36 $
  531. X * $Log:    rsdclnt.c,v $
  532. X * Revision 1.2  91/03/03  17:52:36  deke
  533. X * changed stats to lstats to avoid name clash: required by change in rstat.h
  534. X *
  535. X */
  536. X
  537. X#include <stdio.h>
  538. X#include <rpc/rpc.h>
  539. X#include <rpcsvc/rstat.h>
  540. X#include "config.h"
  541. X
  542. Xmain(argc, argv, envp)
  543. Xint argc;
  544. Xchar *argv[];
  545. Xchar *envp[];
  546. X{
  547. X
  548. Xstruct statstime lstats;
  549. XFILE *fd,*fopen();
  550. Xchar *fgets();
  551. Xint getstats();
  552. X
  553. Xint start,             /* where in the argv the command begins */
  554. X    ppgrp,            /* parent process group            */
  555. X    command,            /* whether there is a command         */
  556. X    verbose_mode,         /* all possible output            */
  557. X    quiet_mode;            /* no output                */
  558. X
  559. Xchar *path=RSH;
  560. X
  561. Xchar *dir,*pname;
  562. Xchar *cmd_exec[MAXSHBUF],    /* command to execute (local)        */
  563. X     *rcmd_exec[MAXSHBUF],    /* command to execute (remote)        */
  564. X     dbuf[MAXSHBUF],        /* working directory placeholder    */
  565. X     host[MAXHOST],        /* hostname placeholder            */
  566. X     best_host[MAXHOST],    /* hostname placeholder            */
  567. X     fentry[MAXLINE];        /* file buffer */
  568. X
  569. Xfloat my_sfactor,
  570. X      best_sfactor,
  571. X      factor, limit,        /* file variables            */
  572. X      load;
  573. X
  574. X    pname = *argv;            /* Name of this program  */
  575. X    verbose_mode=0,quiet_mode=0;    /* Default is neither    */
  576. X    best_sfactor=MAXFLOAT;         /* Practically infinity! */
  577. X     command=1;            /* There is a command     */
  578. X
  579. X /* Check arguments. 
  580. X  *
  581. X  * if argc=1 then verbose=Y and command=NULL
  582. X  * if argc>=2 check for flags:
  583. X  *    -v=verbose (full output),  -q=quiet (don't output machine selection)
  584. X  *    with no flags, only machine selection will be output
  585. X  *    The above flags are mutually exclusive.  v overrides q
  586. X  *
  587. X  *    Additional arguments are taken to be a command.  No sanity checking
  588. X  *    will be done.  When a machine is selected, the command will be sent
  589. X  *    to that machine as a shell command.
  590. X  *
  591. X  */
  592. X
  593. X if (argc == 1) {
  594. X    command=0;            /* no command to execute */
  595. X    verbose_mode=1;            /* verbose mode         */
  596. X }
  597. X else {
  598. X     start=1;
  599. X     if(!strcmp(argv[1],"-q")){
  600. X      quiet_mode=1;            /* quiet mode - no output */
  601. X      start=2;
  602. X      if(argc == 2) exit(0);        /* No command, no output! */
  603. X     } 
  604. X     if(!strcmp(argv[1],"-v")){
  605. X      verbose_mode=1;            /* verbose mode         */
  606. X      start=2;
  607. X      if(argc == 2) command=0;        /* No command - verbose   */
  608. X     } 
  609. X }
  610. X if(command){
  611. X    for( ; start<argc ; start++){
  612. X        strcat(cmd_exec," "); strcat(cmd_exec,argv[start]);
  613. X    }
  614. X }
  615. X
  616. X
  617. X if((fd=fopen(CONFIGFILE,"r"))==0){
  618. X     fprintf(stderr,"Error opening configuration file\n");
  619. X     exit(1);
  620. X }
  621. X
  622. X    while((fgets(fentry,MAXLINE,fd))!=NULL){
  623. X       sscanf(fentry,"%s %f %f",host,&factor,&limit);
  624. X       if(fentry[0]=='#') continue;     /*ignore comments*/
  625. X        
  626. X       if(verbose_mode)
  627. X          printf("\nHOST=%s\tFACTOR=%.2f\tLIMIT=%.2f\n",host,factor,limit);
  628. X       
  629. X       if(getstats(host,&lstats) !=0){
  630. X        load=MAXFLOAT;            /* skip this one */
  631. X       } 
  632. X       else {
  633. X        load=loadavg(&lstats,0);    
  634. X       }
  635. X
  636. X       if( load > limit){
  637. X          if(verbose_mode) printf("Host %s is over defined limit\n",host);
  638. X          continue;
  639. X          }
  640. X
  641. X       my_sfactor=100*(load/factor);
  642. X
  643. X       if(verbose_mode)
  644. X        printf("Load avg=%.3f\tSelection factor=%.3f\n",
  645. X            load,my_sfactor);
  646. X
  647. X       if(best_sfactor>my_sfactor){
  648. X        best_sfactor=my_sfactor;
  649. X        strcpy(best_host,host);
  650. X       }
  651. X    } /*endwhile */
  652. X
  653. X    if(verbose_mode)
  654. X       printf("Selected host: <%s> factor=<%.3f>\n",best_host,best_sfactor);
  655. X
  656. X    if(command){
  657. X        sprintf(rcmd_exec,"(cd %s;%s)",getwd(dbuf),cmd_exec);
  658. X        if(!quiet_mode){ /* print if not quiet_mode */
  659. X           printf("\nrsh %s %s &\n",best_host,rcmd_exec); 
  660. X        }
  661. X        ppgrp = getpgrp(getppid());
  662. X        if (fork())
  663. X        exit(0);
  664. X        if(setpgrp(getpid(), ppgrp)) 
  665. X        perror("stepgrp");
  666. X        execle(path,path,best_host,rcmd_exec,(char *)0,envp); exit(0);
  667. X        perror("");
  668. X    }
  669. Xexit(0);
  670. X}
  671. X
  672. Xgetstats(hostname,lstats)
  673. Xchar *hostname;
  674. Xstruct statstime *lstats;
  675. X{
  676. Xint c;
  677. X    c=rstat(hostname,lstats);    /* rstat seems to return:        */
  678. X                /*    0  on success            */
  679. X                /*    13 on hostname lookup fail  */
  680. X                /*    14 on connection timeout    */
  681. X                /*    15 on "rstat not supported" */
  682. X    /*  I chose to generate my own error messages.  perror() didn't */
  683. X    /*    give error messages I liked.  Switch back to perror if you  */
  684. X    /*    care to.                            */
  685. X
  686. X    switch(c){
  687. X    case 0:
  688. X        break;
  689. X    case 13:
  690. X        fprintf(stderr,"rstat error (%d): ",c);
  691. X        fprintf(stderr,"host %s is unknown.\n",hostname);
  692. X        break;
  693. X    case 14:
  694. X        fprintf(stderr,"rstat error (%d): ",c);
  695. X        fprintf(stderr,"host %s is down or unreachable.\n",hostname);
  696. X        break;
  697. X    case 15:
  698. X        fprintf(stderr,"rstat error (%d): ",c);
  699. X        fprintf(stderr,"host %s does not support protocol.\n",hostname);
  700. X        break;
  701. X    default:
  702. X        fprintf(stderr,"rstat error (%d): ",c);
  703. X            fprintf(stderr,"unknown error\n");
  704. X        break;
  705. X    }
  706. X    return(c);
  707. X}
  708. END_OF_FILE
  709.   if test 5598 -ne `wc -c <'rsdclnt.c'`; then
  710.     echo shar: \"'rsdclnt.c'\" unpacked with wrong size!
  711.   fi
  712.   # end of 'rsdclnt.c'
  713. fi
  714. if test -f 'srvclnt.c' -a "${1}" != "-c" ; then 
  715.   echo shar: Will not clobber existing file \"'srvclnt.c'\"
  716. else
  717.   echo shar: Extracting \"'srvclnt.c'\" \(5875 characters\)
  718.   sed "s/^X//" >'srvclnt.c' <<'END_OF_FILE'
  719. X/*
  720. X * Copyright (c) 1989, University of Rochester
  721. X * Department of Electrical Engineering
  722. X * All rights reserved.
  723. X *
  724. X * Redistribution and use in source and binary forms are permitted
  725. X * provided that the above copyright notice and this paragraph are
  726. X * duplicated in all such forms and that any documentation,
  727. X * advertising materials, and other materials related to such
  728. X * distribution and use acknowledge that the software was developed
  729. X * at the University of Rochester.
  730. X *
  731. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  732. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  733. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  734. X */
  735. X
  736. X/* srvclnt.c version 1.1  3/7/89
  737. X * for the 'lb' load balancer - by Deke Kassabian
  738. X *
  739. X *   -Deke Kassabian, University of Rochester EE Department
  740. X *   ( deke@ee.rochester.edu )  (716) 275-3106
  741. X */
  742. X
  743. X#include <sys/param.h>
  744. X#include <sys/socket.h>
  745. X#include <netinet/in.h>
  746. X#include <netdb.h>
  747. X#include <stdio.h>
  748. X#include <string.h>
  749. X#include "stats.h"
  750. X#include "config.h"
  751. X
  752. Xchar *pname;
  753. Xshort    server = 0;            /* indicates we aren't server    */
  754. Xstruct    sockaddr_in sin;        /* address of remote host    */
  755. X
  756. Xmain(argc, argv, envp)
  757. Xint argc;
  758. Xchar **argv;
  759. Xchar **envp;
  760. X{
  761. X    FILE *fd,*fopen();
  762. X
  763. Xint start,             /* where in the argv the command begins */
  764. X    ppgrp,            /* parent process group            */
  765. X    command,            /* whether there is a command         */
  766. X    verbose_mode,         /* all possible output            */
  767. X    quiet_mode;            /* no output                */
  768. X
  769. Xchar *path=RSH;
  770. X
  771. Xchar *dir;
  772. Xchar *cmd_exec[MAXSHBUF],    /* command to execute (local)        */
  773. X     *rcmd_exec[MAXSHBUF],    /* command to execute (remote)        */
  774. X     dbuf[MAXSHBUF],        /* working directory placeholder    */
  775. X     host[MAXHOST],        /* hostname placeholder            */
  776. X     best_host[MAXHOST],    /* hostname placeholder            */
  777. X     fentry[MAXLINE];        /* file entry                     */
  778. X
  779. Xfloat my_sfactor,
  780. X      best_sfactor,
  781. X      load,
  782. X      factor,limit;        /* file variables            */
  783. X
  784. X    int socktype;
  785. X    register int s;
  786. X    char buf[10240];
  787. X    struct hostent *hp;
  788. X    struct servent *sp;
  789. X    char *servtype;
  790. X    struct hostent *gethostbyname();
  791. X    struct servent *getservbyname();
  792. X
  793. X    pname = *argv;            /* Name of this program  */
  794. X
  795. X    verbose_mode=0,quiet_mode=0;    /* Default is neither    */
  796. X    best_sfactor=MAXFLOAT;         /* Practically infinity! */
  797. X     command=1;            /* There is a command     */
  798. X
  799. X /* Check arguments. 
  800. X  *
  801. X  * if argc=1 then verbose=Y and command=NULL
  802. X  * if argc>=2 check for flags:
  803. X  *    -v=verbose (full output),  -q=quiet (don't output machine selection)
  804. X  *    with no flags, only machine selection will be output
  805. X  *    The above flags are mutually exclusive.  v overrides q
  806. X  *
  807. X  *    Additional arguments are taken to be a command.  No sanity checking
  808. X  *    will be done.  When a machine is selected, the command will be run
  809. X  *    on that machine
  810. X  *
  811. X  */
  812. X
  813. X if (argc == 1) {
  814. X    command=0;            /* no command to execute */
  815. X    verbose_mode=1;            /* verbose mode         */
  816. X    }
  817. X else {
  818. X     start=1;
  819. X     if(!strcmp(argv[1],"-q")){
  820. X      quiet_mode=1;            /* quiet mode - no output */
  821. X      start=2;
  822. X      if(argc == 2) exit(0);        /* No command, no output! */
  823. X     } 
  824. X     if(!strcmp(argv[1],"-v")){
  825. X      verbose_mode=1;            /* verbose mode         */
  826. X      start=2;
  827. X      if(argc == 2) command=0;        /* No command - verbose   */
  828. X     } 
  829. X }
  830. X
  831. X  if(command){
  832. X    for( ; start<argc; start++){
  833. X        strcat(cmd_exec," "); strcat(cmd_exec,argv[start]);
  834. X    }
  835. X  }
  836. X
  837. X /* Open the config file */
  838. X if((fd=fopen(CONFIGFILE,"r"))==0){
  839. X     fprintf(stderr,"Error opening configuration file ");
  840. X     exit(1);
  841. X }
  842. X
  843. X /* Set up to use TCP stream sockets.  */
  844. X    servtype = "tcp";
  845. X    socktype = SOCK_STREAM;
  846. X
  847. X /* Look up the port the server lives on.  */
  848. X if ((sp = getservbyname(SERVNAME, servtype)) == NULL) {
  849. X    fprintf(stderr, "%s: %s/%s: service unknown.\n", 
  850. X        pname, SERVNAME, servtype);
  851. X    exit(1);
  852. X    }
  853. X
  854. X /* Read the config file */
  855. X    strcpy(best_host,"localhost");
  856. X    while((fgets(fentry,MAXLINE,fd))!=NULL){
  857. X       sscanf(fentry,"%s %f %f",host,&factor,&limit);
  858. X       if(fentry[0]=='#') continue; /*ignore comments*/
  859. X        
  860. X       if(verbose_mode)
  861. X         printf("\nHOST=%s\tFACTOR=%.2f\tLIMIT=%.2f\n",host,factor,limit);
  862. X       
  863. X
  864. X       /* Look up the host's address.  */
  865. X       if ((hp = gethostbyname(host)) == NULL) {
  866. X        fprintf(stderr, "%s: %s: host unknown.\n", pname, host);
  867. X        exit(1);
  868. X       }
  869. X    
  870. X       /* Get a socket. */
  871. X       if ((s = socket(AF_INET, socktype, 0)) < 0) {
  872. X            error("socket");
  873. X            exit(1);
  874. X       }
  875. X
  876. X        /* Build the server's address.  */
  877. X        sin.sin_port = sp->s_port;
  878. X        sin.sin_family = hp->h_addrtype;
  879. X        bcopy(hp->h_addr, &sin.sin_addr, sizeof(sin.sin_addr));
  880. X
  881. X        /* connect to the remote host.  */
  882. X        if (connect(s, &sin, sizeof(struct sockaddr_in)) < 0) {
  883. X            /* if not quiet mode, print connect error */
  884. X            error("connect");
  885. X            /* can't reach this host, try the next */
  886. X            continue;
  887. X        }
  888. X
  889. X        /* make the request and grab the result */
  890. X        st_send(s,"loadav");
  891. X        st_recv(s,buf,sizeof(buf),"response");
  892. X        sscanf(buf,"%f",&load);
  893. X
  894. X            if( load > limit){
  895. X               if(verbose_mode)
  896. X              printf("Host %s is over defined limit\n",host);
  897. X               continue;
  898. X            }
  899. X
  900. X        my_sfactor=100*( load / factor );
  901. X        if(verbose_mode){
  902. X          printf("Load avg=%.3f ",load);
  903. X          printf("Selection factor=%.2f\n",my_sfactor);
  904. X        }
  905. X        
  906. X        if(best_sfactor>my_sfactor){
  907. X            best_sfactor=my_sfactor;
  908. X            strcpy(best_host,host);
  909. X        }
  910. X
  911. X    } /*endwhile */
  912. X
  913. Xif(verbose_mode)
  914. X   printf("Selected host: <%s> factor=<%.3f>\n",best_host,best_sfactor);
  915. X
  916. X    if(command){
  917. X        sprintf(rcmd_exec,"(cd %s;%s)",getwd(dbuf),cmd_exec);
  918. X        if(!quiet_mode){    /* print if not quiet_mode */
  919. X           printf("\nrsh %s %s &\n",best_host,rcmd_exec);
  920. X        }
  921. X        ppgrp = getpgrp(getppid());
  922. X        if (fork())
  923. X        exit(0);
  924. X        if(setpgrp(getpid(), ppgrp)) 
  925. X        perror("stepgrp");
  926. X        execle(path,path,best_host,rcmd_exec,(char *)0,envp); exit(0);
  927. X        perror("");
  928. X     }
  929. Xexit(0);
  930. X}
  931. X
  932. Xerror(s)
  933. X{
  934. X    fprintf(stderr, "%s: ", pname); perror(s);
  935. X}
  936. END_OF_FILE
  937.   if test 5875 -ne `wc -c <'srvclnt.c'`; then
  938.     echo shar: \"'srvclnt.c'\" unpacked with wrong size!
  939.   fi
  940.   # end of 'srvclnt.c'
  941. fi
  942. if test -f 'st_sendrecv.c' -a "${1}" != "-c" ; then 
  943.   echo shar: Will not clobber existing file \"'st_sendrecv.c'\"
  944. else
  945.   echo shar: Extracting \"'st_sendrecv.c'\" \(1717 characters\)
  946.   sed "s/^X//" >'st_sendrecv.c' <<'END_OF_FILE'
  947. X#ifndef lint
  948. Xstatic char *RCSid = "$Header: /ecn1/src/ecn/statsrv/RCS/st_sendrecv.c,v 1.2 87/10/19 08:37:02 davy Exp $";
  949. X#endif
  950. X/*
  951. X * st_sendrecv.c - stream send/recv functions
  952. X *
  953. X * David A. Curry
  954. X * Purdue University
  955. X * Engineering Computer Network
  956. X * davy@riacs.edu (previously davy@intrepid.ecn.purdue.edu)
  957. X * October, 1987
  958. X *
  959. X * $Log:    st_sendrecv.c,v $
  960. X * Revision 1.2  87/10/19  08:37:02  davy
  961. X * Fixed to catch end of file on socket.
  962. X * 
  963. X * Revision 1.1  87/10/17  21:01:46  davy
  964. X * Initial revision
  965. X * 
  966. X */
  967. X#include <sys/param.h>
  968. X#include <sys/socket.h>
  969. X#include <netinet/in.h>
  970. X#include <syslog.h>
  971. X#include <stdio.h>
  972. X
  973. X#include "stats.h"
  974. X
  975. Xextern char    *pname;
  976. Xextern short    server;
  977. X
  978. X/*
  979. X * st_send - send buf on the socket s.
  980. X */
  981. Xst_send(s, buf)
  982. Xchar *buf;
  983. Xint s;
  984. X{
  985. X    register int cnt;
  986. X
  987. X    /*
  988. X     * We want the length including the null.
  989. X     */
  990. X    cnt = strlen(buf) + 1;
  991. X
  992. X    /*
  993. X     * Send the buffer.
  994. X     */
  995. X    if (send(s, buf, cnt, 0) < 0) {
  996. X        if (server)
  997. X            syslog(LOG_ERR, "send: %m");
  998. X        else
  999. X            error("send");
  1000. X        exit(1);
  1001. X    }
  1002. X}
  1003. X
  1004. X/*
  1005. X * st_recv - receive data of maximum length cnt into the buffer buf on
  1006. X *         socket s.  err describes what we're expecting for the error
  1007. X *         message.
  1008. X */
  1009. Xst_recv(s, buf, cnt, err)
  1010. Xchar *buf, *err;
  1011. Xint s, cnt;
  1012. X{
  1013. X    char c;
  1014. X    register int n;
  1015. X
  1016. X    /*
  1017. X     * Receive a character at a time up to a null.
  1018. X     */
  1019. X    do {
  1020. X        if ((n = recv(s, &c, sizeof(char), 0)) < 0) {
  1021. X            if (server)
  1022. X                syslog(LOG_ERR, "recv: %m");
  1023. X            else
  1024. X                error("recv");
  1025. X            exit(1);
  1026. X        }
  1027. X
  1028. X        /*
  1029. X         * End of file.
  1030. X         */
  1031. X        if (n == 0)
  1032. X            exit(0);
  1033. X
  1034. X        if (--cnt < 0) {
  1035. X            if (server)
  1036. X                syslog(LOG_ERR, "%s too long", err);
  1037. X            else
  1038. X                fprintf(stderr, "%s: %s too long.\n", pname, err);
  1039. X            exit(1);
  1040. X        }
  1041. X
  1042. X        *buf++ = c;
  1043. X    } while (c != '\0');
  1044. X}
  1045. END_OF_FILE
  1046.   if test 1717 -ne `wc -c <'st_sendrecv.c'`; then
  1047.     echo shar: \"'st_sendrecv.c'\" unpacked with wrong size!
  1048.   fi
  1049.   # end of 'st_sendrecv.c'
  1050. fi
  1051. if test -f 'stats.h' -a "${1}" != "-c" ; then 
  1052.   echo shar: Will not clobber existing file \"'stats.h'\"
  1053. else
  1054.   echo shar: Extracting \"'stats.h'\" \(951 characters\)
  1055.   sed "s/^X//" >'stats.h' <<'END_OF_FILE'
  1056. X/*
  1057. X * $Header: /ecn1/src/ecn/statsrv/RCS/stats.h,v 1.2 87/12/17 14:54:27 davy Exp $
  1058. X *
  1059. X * stats.h - definitions for statistics server
  1060. X *
  1061. X * David A. Curry
  1062. X * Purdue University
  1063. X * Engineering Computer Network
  1064. X * davy@intrepid.ecn.purdue.edu
  1065. X * October, 1987
  1066. X *
  1067. X * $Log:    stats.h,v $
  1068. X * Revision 1.2  87/12/17  14:54:27  davy
  1069. X * Added defines for VMUNIX and KMEM.
  1070. X * 
  1071. X * Revision 1.1  87/10/17  21:01:03  davy
  1072. X * Initial revision
  1073. X * 
  1074. X */
  1075. X
  1076. X#define SERVNAME    "statsrv"    /* name of our service        */
  1077. X#define MAXDGRAM    576        /* maximum size of a datagram    */
  1078. X
  1079. X#define KMEM        "/dev/kmem"    /* path to kernel memory    */
  1080. X
  1081. X#if vax || sun || gould || tahoe
  1082. X#define VMUNIX        "/vmunix"    /* path to kernel        */
  1083. X#endif
  1084. X#if sequent
  1085. X#define VMUNIX        "/dynix"
  1086. X#endif
  1087. X
  1088. X/*
  1089. X * For 4.2BSD syslogs.
  1090. X */
  1091. X#ifndef LOG_DAEMON
  1092. X#define LOG_DAEMON    (3<<3)
  1093. X#endif
  1094. X
  1095. Xextern int st_send(), st_recv();    /* stream send/recv functions    */
  1096. Xextern int dg_send(), dg_recv();    /* datagram send/recv functions    */
  1097. END_OF_FILE
  1098.   if test 951 -ne `wc -c <'stats.h'`; then
  1099.     echo shar: \"'stats.h'\" unpacked with wrong size!
  1100.   fi
  1101.   # end of 'stats.h'
  1102. fi
  1103. echo shar: End of archive.
  1104. exit 0
  1105. exit 0 # Just in case...
  1106.